﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;

namespace GameStateManagement
{
    public class Camera : Actor
    {
        // Constants
        private static float fSpringConstant = 200f;
        private static float fDampConstant = 2.0f * (float)Math.Sqrt(fSpringConstant);

        public Matrix m_CameraMatrix;
        public Matrix m_ProjectionMatrix;

        public Vector3 vDisplacement;
        public Vector3 vActualCameraPosition;
        public Vector3 vIdealPosition;
        public Vector3 vSpringAccel;
        public Vector3 vCameraVelocity;

        Actor subject;

        public Camera(Game game)
            : base(game)
        {
            sMeshName = "";

            // Member initialization
            subject = null;
        }

        public override void Update(GameTime gameTime)
        {
            if (subject != null)
            {
                // Spring camera calculations.
                vIdealPosition = subject.m_vWorldPosition - subject.WorldTransform.Forward * 500f;
                vDisplacement = vActualCameraPosition - vIdealPosition;
                vSpringAccel = (-fSpringConstant * vDisplacement) - (fDampConstant * vCameraVelocity);
                vCameraVelocity += vSpringAccel * GameplayScreen.fDelta;
                vActualCameraPosition += vCameraVelocity * GameplayScreen.fDelta;

                // Update the actor's world position.
                this.m_vWorldPosition = vActualCameraPosition;

                // Calculate camera and projection matrices.
                CalculateViewMatrices();
            }
            base.Update(gameTime);
        }

        private void CalculateViewMatrices()
        {
            m_CameraMatrix = Matrix.CreateLookAt(vActualCameraPosition, subject.GetWorldPosition(), subject.WorldTransform.Up);
            m_ProjectionMatrix = Matrix.CreatePerspectiveFieldOfView(MathHelper.ToRadians(70), Game.GraphicsDevice.Viewport.AspectRatio, 0.1f, 20000.0f);
        }

        public void SetSubject(Actor subject)
        {
            this.subject = subject;
        }
    }
}
